<template>
  <div class="app-container">
    <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
      <el-form-item label="所属项目" prop="projectId">
        <el-select v-model="queryParams.projectId"
                   placeholder="请选择所属项目"
                   clearable
                   @keyup.enter.native="handleQuery">
          <el-option
            v-for="dict in projectOptions"
            :key="dict.projectId"
            :label="dict.projectName"
            :value="dict.projectId"
          />
        </el-select>
      </el-form-item>
      <el-form-item label="设备编号" prop="deviceCode">
        <el-input
          v-model="queryParams.deviceCode"
          placeholder="请输入设备编号"
          clearable
          @keyup.enter.native="handleQuery"
        />
      </el-form-item>
      <el-form-item label="设备名字" prop="deviceName">
        <el-input
          v-model="queryParams.deviceName"
          placeholder="请输入设备名字"
          clearable
          @keyup.enter.native="handleQuery"
        />
      </el-form-item>
      <el-form-item label="是否启用" prop="status">
        <el-select v-model="queryParams.status" placeholder="请选择是否启用" clearable>
          <el-option
            v-for="dict in dict.type.app_status"
            :key="dict.value"
            :label="dict.label"
            :value="dict.value"
          />
        </el-select>
      </el-form-item>
      <el-form-item label="设备类型" prop="type">
        <el-select v-model="queryParams.type" placeholder="请选择设备类型" clearable>
          <el-option
            v-for="dict in dict.type.app_device_type"
            :key="dict.value"
            :label="dict.label"
            :value="dict.value"
          />
        </el-select>
      </el-form-item>
      <el-form-item label="是否运行" prop="type">
        <el-select v-model="queryParams.isRunning" placeholder="请选择是否运行" clearable>
          <el-option
            v-for="dict in dict.type.app_yes_no"
            :key="dict.value"
            :label="dict.label"
            :value="dict.value"
          />
        </el-select>
      </el-form-item>
      <el-form-item label="是否异常" prop="type">
        <el-select v-model="queryParams.isException" placeholder="请选择是否运行" clearable>
          <el-option
            v-for="dict in dict.type.app_yes_no"
            :key="dict.value"
            :label="dict.label"
            :value="dict.value"
          />
        </el-select>
      </el-form-item>
      <el-form-item>
        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
      </el-form-item>
    </el-form>

    <el-row :gutter="10" class="mb8">
      <el-col :span="1.5">
        <el-button
          type="primary"
          plain
          icon="el-icon-plus"
          size="mini"
          @click="handleAdd"
          v-hasPermi="['app:device:add']"
        >新增
        </el-button>
      </el-col>
      <el-col :span="1.5">
        <el-button
          type="info"
          plain
          icon="el-icon-upload"
          size="mini"
          @click="handleUpload"
          v-hasPermi="['app:device:import']"
        >导入
        </el-button>
      </el-col>
      <el-col :span="1.5">
        <el-button
          type="info"
          plain
          icon="el-icon-sort"
          size="mini"
          @click="toggleExpandAll"
        >展开/折叠
        </el-button>
      </el-col>
      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
    </el-row>

    <el-table
      v-if="refreshTable"
      v-loading="loading"
      :data="deviceList"
      row-key="deviceId"
      border
      :default-expand-all="isExpandAll"
      :tree-props="{children: 'children', hasChildren: 'hasChildren'}"
    >
      <el-table-column label="ID" align="center" prop="deviceId"/>
      <el-table-column label="设备名字" align="center" prop="deviceName"/>
      <el-table-column label="所属项目" align="center" prop="projectName">
        <template slot-scope="scope">
          <div v-if="scope.row.projectName">{{ scope.row.projectName }}</div>
        </template>
      </el-table-column>
      <el-table-column label="连接的网关" align="center" prop="gatewayName">
        <template slot-scope="scope">
          <div v-if="scope.row.gatewayName">{{ scope.row.gatewayName }}</div>
        </template>
      </el-table-column>
      <el-table-column label="设备编号" align="center" prop="deviceCode"/>
      <el-table-column label="设备类型" align="center" prop="type">
        <template slot-scope="scope">
          <dict-tag :options="dict.type.app_device_type" :value="scope.row.type"/>
        </template>
      </el-table-column>
<!--      <el-table-column label="管理员" align="center" prop="admin">-->
<!--        <template slot-scope="scope">-->
<!--          <span v-for="(item,index) in scope.row.admin" :key="index">-->
<!--          <span-->
<!--            :index="index">-->
<!--              {{ item.userName }}-->
<!--          </span>-->
<!--          <span v-if="scope.row.admin.length > 1 && index !== scope.row.admin.length - 1">，</span>-->
<!--          </span>-->
<!--        </template>-->
<!--      </el-table-column>-->
<!--      <el-table-column label="操作员" align="center" prop="operator">-->
<!--        <template slot-scope="scope">-->
<!--          <span v-for="(item,index) in scope.row.operator" :key="index">-->
<!--          <span-->
<!--            :index="index">-->
<!--              {{ item.userName }}-->
<!--          </span>-->
<!--          <span v-if="scope.row.operator.length > 1 && index !== scope.row.operator.length - 1">，</span>-->
<!--          </span>-->
<!--        </template>-->
<!--      </el-table-column>-->
      <el-table-column label="是否启用" align="center" prop="status">
        <template slot-scope="scope">
          <dict-tag :options="dict.type.app_status" :value="scope.row.status"/>
        </template>
      </el-table-column>
      <el-table-column label="是否在线" align="center" prop="isRunning">
        <template slot-scope="scope">
          <dict-tag v-if="scope.row.isOnline != null && scope.row.isOnline !== ''" :options="dict.type.app_yes_no"
                    :value="scope.row.isOnline"/>
        </template>
      </el-table-column>
      <el-table-column label="是否运行" align="center" prop="isRunning">
        <template slot-scope="scope">
          <dict-tag v-if="scope.row.isRunning != null && scope.row.isRunning !== ''" :options="dict.type.app_yes_no"
                    :value="scope.row.isRunning"/>
        </template>
      </el-table-column>
      <el-table-column label="是否异常" align="center" prop="isException">
        <template slot-scope="scope">
          <dict-tag v-if="scope.row.isException != null && scope.row.isException !== ''" :options="dict.type.app_yes_no"
                    :value="scope.row.isException"/>
        </template>
      </el-table-column>
      <el-table-column label="是否演示设备" align="center" prop="isShow">
        <template slot-scope="scope">
          <dict-tag v-if="scope.row.isShow != null && scope.row.isShow !== ''" :options="dict.type.app_yes_no"
                    :value="scope.row.isShow"/>
        </template>
      </el-table-column>
      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
        <template slot-scope="scope">
          <el-button
            size="mini"
            type="text"
            icon="el-icon-edit"
            @click="handleUpdate(scope.row)"
            v-hasPermi="['app:device:edit']"
          >修改
          </el-button>
          <el-button
            size="mini"
            type="text"
            icon="el-icon-plus"
            @click="handleAdd(scope.row)"
            v-hasPermi="['app:device:add']"
          >新增
          </el-button>
          <el-button
            size="mini"
            type="text"
            icon="el-icon-delete"
            @click="handleDelete(scope.row)"
            v-hasPermi="['app:device:remove']"
          >删除
          </el-button>
          <el-dropdown size="mini" @command="(command) => handleCommand(command, scope.row)"
                       v-hasPermi="['app:device:list']">
            <span class="el-dropdown-link">
              <i class="el-icon-d-arrow-right el-icon--right"></i>更多
            </span>
            <el-dropdown-menu slot="dropdown">
              <el-dropdown-item command="handleAdmin" icon="el-icon-circle-check"
                                v-hasPermi="['app:device:list']">管理员
              </el-dropdown-item>
              <el-dropdown-item command="handleOperator" icon="el-icon-circle-check"
                                v-hasPermi="['app:device:list']">操作员
              </el-dropdown-item>
              <el-dropdown-item command="handleDataScope" icon="el-icon-circle-check"
                                v-hasPermi="['app:device:edit']">所属部门
              </el-dropdown-item>
              <el-dropdown-item command="handlePlaceScope" icon="el-icon-circle-check"
                                v-hasPermi="['app:device:edit']">空间位置
              </el-dropdown-item>
              <el-dropdown-item command="copyDevice" icon="el-icon-plus"
                                v-hasPermi="['app:device:add']">复制设备
              </el-dropdown-item>
            </el-dropdown-menu>
          </el-dropdown>
        </template>
      </el-table-column>
    </el-table>

    <!-- 添加或修改运行设备对话框 -->
    <el-dialog :title="title" :visible.sync="open" width="680px" append-to-body>
      <el-form ref="form" :model="form" :rules="rules" label-width="100px">
        <el-row>
          <el-col :span="24">
            <el-form-item label="上级设备" prop="parentId">
              <treeselect
                v-model="form.parentId"
                :options="deviceOptions"
                :normalizer="normalizer"
                :show-count="true"
                @select="parentChange"
                placeholder="选择上级设备"/>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="12">
            <el-form-item label="设备名字" prop="deviceName">
              <el-input v-model="form.deviceName" placeholder="请输入设备名字"/>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="是否演示设备">
              <el-radio-group v-model="form.isShow">
                <el-radio
                  v-for="dict in dict.type.app_yes_no"
                  :key="dict.value"
                  :label="dict.value"
                >{{ dict.label }}
                </el-radio>
              </el-radio-group>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="12">
            <el-form-item label="生产厂商" prop="manufactor">
              <el-input v-model="form.manufactor" placeholder="请输入设备生产厂商"/>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="品牌" prop="brand">
              <el-input v-model="form.brand" placeholder="请输入设备品牌"/>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="12">
            <el-form-item label="设备型号" prop="model">
              <el-input v-model="form.model" placeholder="请输入设备型号"/>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="购置日期" prop="acquisitionDate">
              <el-date-picker
                v-model="form.acquisitionDate"
                type="date"
                placeholder="请选择维保日期">
              </el-date-picker>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="12">
            <el-form-item label="维保单位" prop="maintenanceUnit">
              <el-input v-model="form.maintenanceUnit" placeholder="请输入维保单位"/>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="维保日期" prop="maintenanceDate">
              <el-date-picker
                v-model="form.maintenanceDate"
                type="date"
                placeholder="请选择维保日期">
              </el-date-picker>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="12">
            <el-form-item label="设备编号" prop="deviceCode">
              <el-input v-model="form.deviceCode" placeholder="请输入设备编号"/>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="所属项目" prop="projectId">
              <el-select v-model="form.projectId" placeholder="请选择所属项目">
                <el-option
                  v-for="dict in projectOptions"
                  :key="dict.projectId"
                  :label="dict.projectName"
                  :value="dict.projectId"
                ></el-option>
              </el-select>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="12">
            <el-form-item label="额定功率" prop="ratedPower">
              <el-input-number v-model="form.ratedPower" :min="0" controls-position="right"
                               :disabled="form.subCount > 0"/>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="网关" prop="gatewayId">
              <el-select v-model="form.gatewayId" placeholder="请选择网关" clearable>
                <el-option
                  v-for="dict in gatewayOptions"
                  :key="dict.gatewayId"
                  :label="dict.gatewayName"
                  :value="dict.gatewayId"
                ></el-option>
              </el-select>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="12">
            <el-form-item label="设备类型" prop="type">
              <el-select v-model="form.type" placeholder="请选择设备类型">
                <el-option
                  v-for="dict in dict.type.app_device_type"
                  :key="dict.value"
                  :label="dict.label"
                  :value="dict.value"
                ></el-option>
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="是否启用">
              <el-radio-group v-model="form.status">
                <el-radio
                  v-for="dict in dict.type.app_status"
                  :key="dict.value"
                  :label="dict.value"
                >{{ dict.label }}
                </el-radio>
              </el-radio-group>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="12">
            <el-form-item label="是否运行">
              <el-radio-group v-model="form.isRunning">
                <el-radio
                  v-for="dict in dict.type.app_yes_no"
                  :key="dict.value"
                  :label="dict.value"
                >{{ dict.label }}
                </el-radio>
              </el-radio-group>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="是否异常">
              <el-radio-group v-model="form.isException">
                <el-radio
                  v-for="dict in dict.type.app_yes_no"
                  :key="dict.value"
                  :label="dict.value"
                >{{ dict.label }}
                </el-radio>
              </el-radio-group>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="12">
            <el-form-item label="设备管理员" prop="adminIds">
              <el-select v-model="form.adminIds" multiple placeholder="请选设备管理员">
                <el-option
                  v-for="item in userOptions"
                  :key="item.userId"
                  :label="item.userName"
                  :value="item.userId"
                  :disabled="item.status === 1"
                ></el-option>
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="操作员" prop="operatorIds">
              <el-select v-model="form.operatorIds" multiple placeholder="请选操作员">
                <el-option
                  v-for="item in userOptions"
                  :key="item.userId"
                  :label="item.userName"
                  :value="item.userId"
                  :disabled="item.status === 1"
                ></el-option>
              </el-select>
            </el-form-item>
          </el-col>
        </el-row>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button type="primary" @click="submitForm">确 定</el-button>
        <el-button @click="cancel">取 消</el-button>
      </div>
    </el-dialog>

    <!-- 分配角色数据权限对话框 -->
    <el-dialog :title="title" :visible.sync="openDataScope" width="500px" append-to-body>
      <el-form :model="form" label-width="80px">
        <el-form-item label="设备名称">
          <el-input v-model="form.deviceName" :disabled="true"/>
        </el-form-item>
        <el-form-item label="部门权限">
          <el-checkbox v-model="deptExpand" @change="handleCheckedTreeExpand($event, 'dept')">展开/折叠</el-checkbox>
          <el-checkbox v-model="deptNodeAll" @change="handleCheckedTreeNodeAll($event, 'dept')">全选/全不选</el-checkbox>
          <el-checkbox v-model="form.deptCheckStrictly" @change="handleCheckedTreeConnect($event, 'dept')">父子联动
          </el-checkbox>
          <el-tree
            class="tree-border"
            :data="deptOptions"
            show-checkbox
            :default-expand-all="isExpandAll"
            ref="dept"
            node-key="id"
            :check-strictly="!form.deptCheckStrictly"
            empty-text="加载中，请稍候"
            :props="defaultProps"
          ></el-tree>
        </el-form-item>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button type="primary" @click="submitDataScope">确 定</el-button>
        <el-button @click="cancelDataScope">取 消</el-button>
      </div>
    </el-dialog>
    <!-- 分配角色空间权限对话框 -->
    <el-dialog :title="title" :visible.sync="openPlaceScope" width="500px" append-to-body>
      <el-form :model="form" label-width="80px">
        <el-form-item label="设备名称">
          <el-input v-model="form.deviceName" :disabled="true"/>
        </el-form-item>
        <el-form-item label="空间权限">
          <el-checkbox v-model="placeExpand" @change="handleCheckedTreeExpand($event, 'place')">展开/折叠</el-checkbox>
          <el-checkbox v-model="placeNodeAll" @change="handleCheckedTreeNodeAll($event, 'place')">全选/全不选</el-checkbox>
          <el-checkbox v-model="form.placeCheckStrictly" @change="handleCheckedTreeConnect($event, 'place')">父子联动
          </el-checkbox>
          <el-tree
            class="tree-border"
            :data="placeOptions"
            show-checkbox
            :default-expand-all="isExpandAll"
            ref="place"
            node-key="id"
            :check-strictly="!form.placeCheckStrictly"
            empty-text="加载中，请稍候"
            :props="defaultProps"
          ></el-tree>
        </el-form-item>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button type="primary" @click="submitPlaceScope">确 定</el-button>
        <el-button @click="cancelPlaceScope">取 消</el-button>
      </div>
    </el-dialog>
    <!-- 设备复制对话框 -->
    <el-dialog title="复制设备" :visible.sync="openCopyDevice" width="450px" append-to-body>
      <el-form :model="formDevice" label-width="120px">
        <el-form-item label="复制设备数量">
          <el-input-number v-model="formDevice.num" />
        </el-form-item>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button type="primary" @click="submitCopyDevice">确 定</el-button>
        <el-button @click="cancelCopyDevice">取 消</el-button>
      </div>
    </el-dialog>
    <el-dialog :title="userTitle" :visible.sync="userOpen" width="500px" append-to-body>
      <div>
        <el-table :data="userList"  v-loading="userLoading" row-key="userId">
          <el-table-column label="用户名" prop="userName" />
          <el-table-column label="手机号" prop="phonenumber" />
          <el-table-column label="姓名" prop="nickName" />
        </el-table>
        <div slot="footer" class="dialog-footer">
          <el-button @click="cancelUser">关 闭</el-button>
        </div>
      </div>
    </el-dialog>
    <el-dialog title="设备导入" :visible.sync="isUpload" width="800px" append-to-body :close-on-click-modal="false">
      <el-form  ref="formUpload" :model="formUpload" size="small" style="width: 750px">
        <div style="display: flex;">
          <div style="width: 350px;height: 100%">
            <el-upload
              :action="uploadFileUrl+'?sid='+this.sid"
              :before-upload="handleBeforeUpload"
              :data="deployInfo"
              :headers="headers"
              :on-error="handleUploadError"
              :on-exceed="handleExceed"
              :on-success="handleUploadSuccess"
              class="upload-demo"
              :multiple="false"
              :show-file-list="false"
              accept=".xls,.xlsx"
              :disabled="haveUploaded"
              drag
            >
              <i class="el-icon-upload"/>
              <div class="el-upload__text">
                将文件拖到此处，或
                <em>点击上传</em>
              </div>
              <div slot="tip" class="el-upload__tip">请上传设备导入文件。
                <el-link type="primary" :underline="false" style="font-size:12px;vertical-align: baseline;" @click="importTemplate">下载模板</el-link>
              </div>
            </el-upload>
          </div>
          <div style="display: flex;flex: 1;height: 100%;">
            <div class="chart-wrapper">
              <el-steps :space="200" style="width: 300px" :active="processTag" finish-status="success">
                <el-step title="上传"/>
                <el-step title="验证" :description="uploadFileTime.verifyTime ? '耗时约:'+uploadFileTime.verifyTime+'秒' : ''"/>
                <el-step title="导入" :description="uploadFileTime.addTime ? '耗时约:'+uploadFileTime.addTime+'秒' : ''"/>
              </el-steps>
            </div>
          </div>
        </div>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button @click="cancel">取 消</el-button>
      </div>
    </el-dialog>

  </div>
</template>

<script>
import {
  addDevice,
  dataScope,
  delDevice,
  deptTreeSelect,
  getDevice,
  listDevice,
  listDeviceExcludeChild,
  placeScope,
  placeTreeSelect,
  updateDevice,
  copyDevice,
  listOperator,
  listAdmin
} from "@/api/app/device";
import Treeselect from "@riophae/vue-treeselect";
import "@riophae/vue-treeselect/dist/vue-treeselect.css";
import {listAll} from "@/api/app/gateway";
import {listAllProject} from "@/api/app/project";
import {listAllUser} from "@/api/system/user";
import {getToken} from "@/utils/auth";

export default {
  name: "Device",
  dicts: ['app_device_type', 'app_status', 'app_yes_no'],
  components: {Treeselect},
  data() {
    return {
      // 遮罩层
      loading: true,
      userLoading: false,
      // 显示搜索条件
      showSearch: true,
      newAdd: false,
      newData: {},
      // 运行设备表格数据
      deviceList: [],
      // 运行设备树选项
      deviceOptions: [],
      gatewayOptions: [],
      projectOptions: [],
      // 弹出层标题
      title: "",
      userTitle: '',
      // 是否显示弹出层
      open: false,
      // 是否上传
      isUpload: false,
      deployInfo: {},
      userOpen: false,
      // 是否显示弹出层（数据权限）
      openDataScope: false,
      // 是否显示弹出层（数据权限）
      openPlaceScope: false,
      openCopyDevice: false,
      // 是否展开，默认全部展开
      isExpandAll: false,
      // 重新渲染表格状态
      refreshTable: true,
      deptExpand: true,
      deptNodeAll: false,
      placeExpand: true,
      placeNodeAll: false,
      // 部门列表
      deptOptions: [],
      // 空间列表
      placeOptions: [],
      // 人员列表
      userOptions: [],
      // 查询参数
      queryParams: {
        parentId: null,
        projectId: null,
        gatewayId: null,
        deviceCode: null,
        deviceName: null,
        subCount: null,
        ratedPower: null,
        status: null,
        type: null,
        isRunning: null,
        isException: null
      },
      processTag: 0,
      // 表单参数
      form: {},
      formUpload: {},
      formDevice: {},
      defaultProps: {
        children: "children",
        label: "label"
      },
      userList:[],
      // 表单校验
      rules: {
        parentId: [
          {required: true, message: "上级设备不能为空", trigger: "blur"}
        ],
        deviceName: [
          {required: true, message: "设备名称不能为空", trigger: "blur"}
        ],
        deviceCode: [
          {required: true, message: "设备编号不能为空", trigger: "blur"}
        ],
        manufactor: [
          {required: true, message: "生产厂商不能为空", trigger: "blur"}
        ],
        brand: [
          {required: true, message: "品牌不能为空", trigger: "blur"}
        ],
        model: [
          {required: true, message: "设备型号不能为空", trigger: "blur"}
        ],
        projectId: [
          {required: true, message: "所属项目不能为空", trigger: "blur"}
        ],
        status: [
          {required: true, message: "是否启用不能为空", trigger: "blur"}
        ],
        gatewayId: [
          {required: true, message: "网关不能为空", trigger: "blur"}
        ],
        type: [
          {required: true, message: "设备类型不能为空", trigger: "blur"}
        ],
        adminIds: [
          {required: true, message: "设备管理员不能为空", trigger: "blur"}
        ],
        operatorIds: [
          {required: true, message: "设备操作员不能为空", trigger: "blur"}
        ],
      },
      uploadFileUrl: process.env.VUE_APP_BASE_API + "/app/device/importData", // 上传的文件服务器地址
      headers: {
        Authorization: "Bearer " + getToken(),
      },
      fileType: ["xls", "xlsx"],
      fileSize: 15,
      uploadFileTime:{},
      haveUploaded: false,
      sid: null,
      timer: null,
    };
  },
  mounted() {
    this.sid = new Date().getTime();
  },
  created() {
    this.getList();
    this.getGateway();
    this.getProject();
    this.getUserList();
  },
  destroyed() {
    if (this.timer){
      clearInterval(this.timer)
    }
    if(this.websock) {
      this.websock.close();
    }
  },
  methods: {
    /** 查询运行设备列表 */
    getList() {
      this.loading = true;
      listDevice(this.queryParams).then(response => {
        this.deviceList = this.handleTree(response.data, "deviceId");
        this.loading = false;
      });
    },
    getGateway() {
      listAll().then(response => {
        this.gatewayOptions = response.data
      })
    },
    getProject() {
      listAllProject().then(response => {
        this.projectOptions = response.data
      })
    },
    getUserList() {
      listAllUser().then(response => {
        this.userOptions = response.data;
      });
    },
    /** 转换设备数据结构 */
    normalizer(node) {
      if (node.children && !node.children.length) {
        delete node.children;
      }
      return {
        id: node.deviceId,
        label: node.deviceName,
        children: node.children
      };
    },
    // 所有部门节点数据
    getDeptAllCheckedKeys() {
      // 目前被选中的部门节点
      let checkedKeys = this.$refs.dept.getCheckedKeys();
      // 半选中的部门节点
      let halfCheckedKeys = this.$refs.dept.getHalfCheckedKeys();
      checkedKeys.unshift.apply(checkedKeys, halfCheckedKeys);
      return checkedKeys;
    },
    // 所有空间位置节点数据
    getPlaceAllCheckedKeys() {
      // 目前被选中的空间位置节点
      let checkedKeys = this.$refs.place.getCheckedKeys();
      // 半选中的空间位置节点
      let halfCheckedKeys = this.$refs.place.getHalfCheckedKeys();
      checkedKeys.unshift.apply(checkedKeys, halfCheckedKeys);
      return checkedKeys;
    },
    /** 根据角色ID查询部门树结构 */
    getDeptTree(deviceId) {
      return deptTreeSelect(deviceId).then(response => {
        this.deptOptions = response.depts;
        return response;
      });
    },
    /** 根据角色ID查询空间位置树结构 */
    getPlaceTree(deviceId) {
      return placeTreeSelect(deviceId).then(response => {
        this.placeOptions = response.places;
        return response;
      });
    },
    // 取消按钮
    cancel() {
      this.open = false;
      this.isUpload = false;
      this.reset();
    },
    // 取消按钮（数据权限）
    cancelDataScope() {
      this.openDataScope = false;
      this.reset();
      if (this.newAdd === true) {
        this.handlePlaceScope(this.newData)
        this.newAdd = false;
      }
    },
    // 取消按钮（空间权限）
    cancelPlaceScope() {
      this.openPlaceScope = false;
      this.reset();
    },
    // 取消按钮（空间权限）
    cancelCopyDevice() {
      this.openCopyDevice = false;
    },
    // 表单重置
    reset() {
      this.deptExpand = true,
        this.deptNodeAll = false,
        this.placeExpand = true,
        this.placeNodeAll = false,
        this.form = {
          parentId: 0,
          gatewayId: null,
          deviceCode: null,
          deviceName: null,
          subCount: 0,
          ratedPower: 0,
          status: "0",
          type: null,
          deptIds: [],
          placeIds: [],
          deptCheckStrictly: true,
          placeCheckStrictly: true,
          isRunning: "1",
          isException: "0",
          isShow: "0",
          brand: null,
          manufactor: null,
          model: null,
          acquisitionDate: null,
          maintenanceUnit: null,
          maintenanceDate: null,
          operatorIds: [],
          adminIds: []
        };
      this.resetForm("form");
    },
    /** 搜索按钮操作 */
    handleQuery() {
      this.getList();
    },
    /** 重置按钮操作 */
    resetQuery() {
      this.resetForm("queryForm");
      this.handleQuery();
    },
    /** 新增按钮操作 */
    handleAdd(row) {
      this.reset();
      this.getTreeSelect();
      if (row != null && row.deviceId) {
        this.form.parentId = row.deviceId;
        this.form.type = row.type;
      } else {
        this.form.parentId = 0;
      }
      this.open = true;
      this.title = "添加运行设备";
    },
    /** 展开/折叠操作 */
    toggleExpandAll() {
      this.refreshTable = false;
      this.isExpandAll = !this.isExpandAll;
      this.$nextTick(() => {
        this.refreshTable = true;
      });
    },
    getTreeSelect() {
      listDevice().then(response => {
        this.deviceOptions = [];
        const device = {deviceId: 0, deviceName: '顶级设备', children: []};
        device.children = this.handleTree(response.data, "deviceId");
        this.deviceOptions.push(device);
      })
    },
    /** 修改按钮操作 */
    handleUpdate(row) {
      this.reset();
      getDevice(row.deviceId).then(response => {
        this.form = response.data;
        this.open = true;
        this.title = "修改运行设备";
        listDeviceExcludeChild(row.deviceId).then(response => {
          // this.deviceOptions = this.handleDeviceTree(response.data, "deviceId");
          // if (this.deviceOptions.length == 0) {
          //   const noResultsOptions = { deviceId: this.form.parentId,
          //     deviceName: this.form.parentName, children: [] };
          //   this.deviceOptions.push(noResultsOptions);
          // }
          this.deviceOptions = [];
          const device = {deviceId: 0, deviceName: '顶级设备', children: []};
          device.children = this.handleTree(response.data, "deviceId");
          this.deviceOptions.push(device);
        });
      });
    },
    /** 提交按钮 */
    submitForm() {
      this.$refs["form"].validate(valid => {
        if (valid) {
          if (this.form.deviceId != null) {
            updateDevice(this.form).then(response => {
              this.$modal.msgSuccess("修改成功");
              this.open = false;
              this.getList();
            });
          } else {
            addDevice(this.form).then(response => {
              this.$modal.msgSuccess("新增成功");
              this.open = false;
              this.getList();
              this.newAdd = true
              this.handleDataScope(response.data)
              this.newData = response.data
            });
          }
        }
      });
    },
    /** 删除按钮操作 */
    handleDelete(row) {
      this.$modal.confirm('是否确认删除名称为"' + row.deviceName + '"的数据项？').then(function () {
        return delDevice(row.deviceId);
      }).then(() => {
        this.getList();
        this.$modal.msgSuccess("删除成功");
      }).catch(() => {
      });
    },
    parentChange(e) {
      console.log(e)
      this.form.type = e.type
    },
    // 树权限（展开/折叠）
    handleCheckedTreeExpand(value, type) {
      if (type == 'dept') {
        let treeList = this.deptOptions;
        for (let i = 0; i < treeList.length; i++) {
          this.$refs.dept.store.nodesMap[treeList[i].id].expanded = value;
        }
      } else if (type == 'place') {
        let treeList = this.placeOptions;
        for (let i = 0; i < treeList.length; i++) {
          this.$refs.place.store.nodesMap[treeList[i].id].expanded = value;
        }

      }
    },
    // 树权限（全选/全不选）
    handleCheckedTreeNodeAll(value, type) {
      if (type == 'dept') {
        this.$refs.dept.setCheckedNodes(value ? this.deptOptions : []);
      } else if (type == 'place') {
        this.$refs.place.setCheckedNodes(value ? this.placeOptions : []);
      }
    },
    // 树权限（父子联动）
    handleCheckedTreeConnect(value, type) {
      if (type == 'dept') {
        this.form.deptCheckStrictly = value ? true : false;
      } else if (type == 'place') {
        this.form.placeCheckStrictly = value ? true : false;
      }
    },
    // 更多操作触发
    handleCommand(command, row) {
      switch (command) {
        case "handlePlaceScope":
          this.handlePlaceScope(row);
          break;
        case "handleDataScope":
          this.handleDataScope(row);
          break;
        case "copyDevice":
          this.copyDevice(row);
          break;
        case "handleAdmin":
          this.handleAdmin(row);
          break;
        case "handleOperator":
          this.handleOperator(row);
          break;
        default:
          break;
      }
    },
    /** 分配部门权限操作 */
    handleDataScope(row) {
      this.reset();
      const deptTreeSelect = this.getDeptTree(row.deviceId);
      getDevice(row.deviceId).then(response => {
        this.form = response.data;
        this.openDataScope = true;
        this.$nextTick(() => {
          deptTreeSelect.then(res => {
            this.$refs.dept.setCheckedKeys(res.checkedKeys);
          });
        });
        this.title = "分配部门权限";
      });
    },
    /** 分配空间权限操作 */
    handlePlaceScope(row) {
      this.reset();
      const placeTreeSelect = this.getPlaceTree(row.deviceId);
      getDevice(row.deviceId).then(response => {
        this.form = response.data;
        this.openPlaceScope = true;
        this.$nextTick(() => {
          placeTreeSelect.then(res => {
            this.$refs.place.setCheckedKeys(res.checkedKeys);
          });
        });
        this.title = "分配空间权限";
      });
    },
    copyDevice(row) {
      this.formDevice.num = 1;
      this.formDevice.deviceId = row.deviceId;
      this.openCopyDevice = true
    },
    /** 提交按钮（数据权限） */
    submitDataScope: function () {
      if (this.form.deviceId !== null && (typeof this.form.deviceId) !== 'undefined') {
        this.form.deptIds = this.getDeptAllCheckedKeys();
        dataScope(this.form).then(response => {
          this.$modal.msgSuccess("修改成功");
          this.openDataScope = false;
          this.getList();
          if (this.newAdd == true) {
            this.handlePlaceScope(this.form)
            this.newAdd = false;
          }
        });
      }
    },
    /** 提交按钮（数据权限） */
    submitPlaceScope: function () {
      if (this.form.deviceId !== null && (typeof this.form.deviceId) !== 'undefined') {
        this.form.placeIds = this.getPlaceAllCheckedKeys();
        placeScope(this.form).then(response => {
          this.$modal.msgSuccess("修改成功");
          this.openPlaceScope = false;
          this.getList();
        });
      }
    },
    /** 提交设备复制 */
    submitCopyDevice: function () {
      if (this.formDevice.deviceId !== null && (typeof this.formDevice.deviceId) !== 'undefined') {
          copyDevice(this.formDevice.deviceId, this.formDevice.num).then(response =>{
            this.$modal.msgSuccess("复制成功");
            this.openCopyDevice = false;
            this.getList();
          })
      }
    },
    handleDeviceTree(data) {
      let childrenListMap = {};
      let nodeIds = {};
      let tree = [];
      data.forEach(d => {
          let parentId = d.parentId;
          if (childrenListMap[parentId] == null) {
            childrenListMap[parentId] = [];
          }
          nodeIds[d.deviceId] = d;
          childrenListMap[parentId].push(d);
        }
      )

      for (let d of data) {
        let parentId = d.parentId;
        if (nodeIds[parentId] == null) {
          let ancestors = d.ancestors;
          if (ancestors != null && (typeof ancestors) != 'undefined' && ancestors.indexOf(',') > -1) {
            let a = ancestors.split(',')
            for (let i = a.length - 1; i > -1; i--) {
              let k = parseInt(a[i]);
              if (nodeIds[k] != null) {
                parentId = k
                break
              }
            }
          }
          if (parentId === d.parentId) {
            tree.push(d);
          }
        }
      }

      for (let t of tree) {
        adaptToChildrenList(t);
      }

      function adaptToChildrenList(o) {
        if (childrenListMap[o.deviceId] !== null && (typeof childrenListMap[o.deviceId]) != 'undefined') {
          o.children = childrenListMap[o.deviceId];
        } else {
          for (let value of data) {
            let ancestors = value.ancestors
            if (ancestors != null && (typeof ancestors) != 'undefined' && ancestors.indexOf(',') > -1) {
              if (ancestors.indexOf(o.deviceId + '') > -1 && value.parentId !== o.deviceId) {
                o.children.push(value)
              }
            }
          }
        }
        if (o.children) {
          for (let c of o.children) {
            adaptToChildrenList(c);
          }
        }
      }
      return tree;
    },
    cancelUser(){
      this.userList = [];
      this.userOpen = false;
      this.userTitle ='';
    },
    handleAdmin(row){
      this.userOpen = true;
      this.userTitle ='管理员列表';
      this.userLoading = true;
      listAdmin(row.deviceId).then(res =>{
        this.userList = res.data;
        this.userLoading = false;
      })

    },
    handleOperator(row){
      this.userOpen = true;
      this.userTitle ='操作员列表';
      this.userLoading = true;
      listOperator(row.deviceId).then(res =>{
        this.userList = res.data;
        this.userLoading = false;
      })
    },
    /** 导入按钮操作 */
    handleUpload() {
      this.isUpload = true;
      this.processTag = 0
      this.uploadFileTime = {};
      this.initWebSocket()
    },
    /** 下载模板操作 */
    importTemplate() {
      this.download('app/device/importTemplate', {
      }, `device_template_${new Date().getTime()}.xlsx`)
    },
    // 上传成功回调
    handleUploadSuccess(res, file) {
      this.$modal.closeLoading();
      if (res.code === 200) {
        this.uploadFileTime = res.data;
        this.$modal.msgSuccess("文件上传成功,进入数据处理");
      } else {
        this.$modal.msgError(res.msg);
        this.processTag = 0;
        this.uploadFileTime = {};
      }
    },
    // 上传前校检格式和大小
    handleBeforeUpload(file) {
      // 校检文件类型
      if (this.fileType) {
        let fileExtension = "";
        if (file.name.lastIndexOf(".") > -1) {
          fileExtension = file.name.slice(file.name.lastIndexOf(".") + 1);
        }
        const isTypeOk = function () {
          this.fileType.forEach((type) => {
            if (file.type.indexOf(type) > -1) return true;
            if (fileExtension && fileExtension.indexOf(type) > -1) return true;
            return false;
          })
        };
        if (!isTypeOk) {
          this.$modal.msgError(`文件格式不正确, 请上传${this.fileType.join("/")}格式文件!`);
          return false;
        }
      }
      // 校检文件大小
      if (this.fileSize) {
        const isLt = file.size / 1024 / 1024 < this.fileSize;
        if (!isLt) {
          this.$modal.msgError(`上传文件大小不能超过 ${this.fileSize} MB!`);
          return false;
        }
      }
      this.$modal.loading("正在上传文件，请稍候...");
      this.processTag = 0;
      this.uploadFileTime = {};
      this.haveUploaded = true;
      return true;
    },
    // 文件个数超出
    handleExceed() {
      this.$modal.msgError(`上传文件数量不能超过 ${this.limit} 个!`);
      this.haveUploaded = false;
    },
    // 监听上传失败
    handleUploadError(e, file, fileList) {
      const msg = JSON.parse(e.message)
      this.haveUploaded = false;
      this.$notify({
        title: msg.message,
        type: 'error',
        duration: 2500
      })
    },
    initWebSocket() {
      console.log(process)
      if (this.sid) {
        const wsUri = process.env.VUE_APP_WS_API + '/webSocket/'+this.sid
        this.websock = new WebSocket(wsUri)
        this.websock.onerror = this.webSocketOnError
        this.websock.onmessage = this.webSocketOnMessage
        this.websock.onopen = function (event){
          console.log('WebSocket 连接已打开')
        }
        this.timer = setInterval(()=>{
          const data = { type: 'HEARTBEAT' };
          if (this.websock.readyState === WebSocket.OPEN) {
            this.websock.send(JSON.stringify(data))
          }
        },10000)
      }
    },
    webSocketOnError(e) {
      this.$notify({
        title: 'WebSocket连接发生错误',
        type: 'error',
        duration: 0
      })
    },
    webSocketOnMessage(e) {
      const data = JSON.parse(e.data)
      if (data.msgType === 'INFO') {
        if (data.msg === '服务器收到文件') {
          this.processTag = 1
        } else if (data.msg === '验证完成，正在进行导入...') {
          this.processTag = 2
        } else if (data.msg === '导入成功') {
          this.processTag = 3
          this.getList()
          this.isUpload = false;
          this.haveUploaded = false;
          this.open = false;
          console.log('导入成功')
        }
        this.$notify({
          title: '',
          message: data.msg,
          type: 'success',
          dangerouslyUseHTMLString: true,
          duration: 10000
        })
      } else if (data.msgType === 'ERROR') {
        this.processTag = 0
        this.uploadFileTime = {};
        this.haveUploaded = false;
        this.$notify({
          title: '',
          message: data.msg,
          dangerouslyUseHTMLString: true,
          type: 'error',
          duration: 0
        })
      }
    },
  }
}
;
</script>
<style>
.chart-wrapper {
  background: #fff;
  padding: 80px 40px 0;
  margin: 0 auto;
}

.is-process .el-step__icon-inner{
  animation: rotate 2s linear infinite;
}
@keyframes rotate {
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(360deg);
  }
}
</style>
